#!/usr/bin/env python
# -*- coding: utf-8 -*-

from abc import ABCMeta, abstractmethod
from typing import Any

from cta.config.base_config import BaseConfig
from cta.config.cross_section_config.multi_factor_config import MultiFactorConfig
from web.constants.k_line_movement_pattern import KLineMovementPattern
from web.dao.commodity_future_date_contract_data_dao import CommodityFutureDateContractDataDao
from web.dao.commodity_future_date_data_dao import CommodityFutureDateDataDao
from web.dao.commodity_future_info_dao import CommodityFutureInfoDao
from web.dao.optimize2_account_dao import Optimize2AccountDao
from web.dao.optimize2_account_log_dao import Optimize2AccountLogDao
from web.dao.optimize2_commodity_future_transaction_record_dao import Optimize2CommodityFutureTransactionRecordDao
from web.dao.quant2_account_dao import Quant2AccountDao
from web.dao.quant2_account_log_dao import Quant2AccountLogDao
from web.dao.quant2_commodity_future_filter_dao import Quant2CommodityFutureFilterDao
from web.dao.quant2_commodity_future_transaction_record_dao import Quant2CommodityFutureTransactionRecordDao
from web.dao.stock_transaction_data_all_dao import StockTransactionDataAllDao
from web.dao.unite_relative_price_index_date_dao import UniteRelativePriceIndexDateDao
from web.domain.responsibility_chain_dto import ResponsibilityChainDto
from web.models.commodity_future_date_contract_data import CommodityFutureDateContractData
from web.models.optimize2_account import Optimize2Account
from web.models.optimize2_account_log import Optimize2AccountLog
from web.models.optimize2_commodity_future_transaction_record import Optimize2CommodityFutureTransactionRecord
from web.models.quant2_account import Quant2Account
from web.models.quant2_account_log import Quant2AccountLog
from web.models.quant2_commodity_future_filter import Quant2CommodityFutureFilter
from web.models.quant2_commodity_future_transaction_record import Quant2CommodityFutureTransactionRecord
from web.models.unite_relative_price_index_date import UniteRelativePriceIndexDate
from web.manager.log_manager import LogManager

Logger = LogManager.get_logger(__name__)

class AbstractAction(metaclass=ABCMeta):
    """
    抽象动作类
    """

    def __init__(self, successor=None):
        self._successor = successor

        self.stock_transaction_data_all_dao = StockTransactionDataAllDao()
        self.commodity_future_date_data_dao = CommodityFutureDateDataDao()
        self.commodity_future_date_contract_data_dao = CommodityFutureDateContractDataDao()
        self.commodity_future_info_dao = CommodityFutureInfoDao()
        self.quant2_commodity_future_filter_dao = Quant2CommodityFutureFilterDao()
        self.quant2_account_dao = Quant2AccountDao()
        self.quant2_commodity_future_transaction_record_dao = Quant2CommodityFutureTransactionRecordDao()
        self.quant2_account_log_dao = Quant2AccountLogDao()
        self.unite_relative_price_index_date_dao = UniteRelativePriceIndexDateDao()
        self.optimize2_account_dao = Optimize2AccountDao()
        self.optimize2_commodity_future_transaction_record_dao = Optimize2CommodityFutureTransactionRecordDao()
        self.optimize2_account_log_dao = Optimize2AccountLogDao()

    def set_successor(self, successor):
        """
        设置下一个动作
        """

        self._successor = successor

    def next(self, responsibility_chain_dto: ResponsibilityChainDto = None):
        if self._successor:
            self._successor.exec(responsibility_chain_dto)

    @abstractmethod
    def exec(self, responsibility_chain_dto: ResponsibilityChainDto = None) -> Any:
        """
        执行
        """

        pass

    def quant2_k_line_movement_pattern_and_close_or_open_position_by_holding_position_time(self, transaction_date):
        """
        根据持仓时间，判断k线形态；判断当天是否应当平仓和开仓。True表示当天应当平仓和开仓，False表示不应当。查询quant2
        """

        quant2_account_list: list[Quant2Account] = self.quant2_account_dao.find_all()
        quant2_account_log_list: list[Quant2AccountLog] = self.quant2_account_log_dao.find_by_account_name_order_by_date_desc(quant2_account_list[0].account_name)

        if quant2_account_log_list is None or len(quant2_account_log_list) == 0:
            return KLineMovementPattern.Fluctuation, True

        # 查询当前的variance20
        unite_relative_price_index_date: UniteRelativePriceIndexDate = self.unite_relative_price_index_date_dao.find_by_transaction_date(transaction_date)

        # 由于数据缺失，因此只能按照震荡形态处理
        if unite_relative_price_index_date is None:
            holding_position_date_number: int = BaseConfig.Fluctuation_Holding_Position_Date_Number
            up_down_percentage_backtrack_max_date: int = BaseConfig.Fluctuation_Up_Down_Percentage_Backtrack_Max_Date
            k_line_movement_pattern: int = KLineMovementPattern.Fluctuation
            Logger.warning("日期[%s]在表c_f_date_contract_data中有数据，但是在表commodity_future_date_data中没有数据，因此只能这种取值，k线形态为[%s]，持仓时间为[%s]，最大回溯为[%s]",
                           transaction_date, k_line_movement_pattern, holding_position_date_number, up_down_percentage_backtrack_max_date)
            if (len(quant2_account_log_list) + 1) % holding_position_date_number == 0:
                return k_line_movement_pattern, True
            else:
                return k_line_movement_pattern, False

        if unite_relative_price_index_date.variance250 <= 40:
        # if 41 <= 40:
            # 震荡形态
            holding_position_date_number: int = BaseConfig.Fluctuation_Holding_Position_Date_Number
            up_down_percentage_backtrack_max_date: int = BaseConfig.Fluctuation_Up_Down_Percentage_Backtrack_Max_Date
            k_line_movement_pattern: int = KLineMovementPattern.Fluctuation
            Logger.info("k线形态为[%s]，250方差为[%s]，持仓时间为[%s]，最大回溯为[%s]", k_line_movement_pattern, unite_relative_price_index_date.variance250, holding_position_date_number,
                        up_down_percentage_backtrack_max_date)
        else:
            # 趋势形态
            holding_position_date_number: int = BaseConfig.Trend_Holding_Position_Date_Number
            up_down_percentage_backtrack_max_date: int = BaseConfig.Trend_Up_Down_Percentage_Backtrack_Max_Date
            k_line_movement_pattern: int = KLineMovementPattern.Trend
            Logger.info("k线形态为[%s]，250方差为[%s]，持仓时间为[%s]，最大回溯为[%s]", k_line_movement_pattern, unite_relative_price_index_date.variance250, holding_position_date_number,
                        up_down_percentage_backtrack_max_date)

        if (len(quant2_account_log_list) + 1) % holding_position_date_number == 0:
            return k_line_movement_pattern, True
        else:
            return k_line_movement_pattern, False

    def quant2_k_line_movement_pattern_and_close_or_open_position_by_holding_position_time_and_commodity_future_date_contract_data(self, transaction_date, commodity_future_date_contract_data: CommodityFutureDateContractData):
        """
        判断k线形态；判断当天是否应当平仓和开仓。True表示当天应当平仓和开仓，False表示不应当。查询quant2
        """

        quant2_account_list: list[Quant2Account] = self.quant2_account_dao.find_all()
        quant2_account_log_list: list[Quant2AccountLog] = self.quant2_account_log_dao.find_by_account_name_order_by_date_desc(quant2_account_list[0].account_name)

        if quant2_account_log_list is None or len(quant2_account_log_list) == 0:
            return KLineMovementPattern.Fluctuation, True

        # 由于数据缺失，因此只能按照震荡形态处理
        if commodity_future_date_contract_data is None or commodity_future_date_contract_data.variance250 is None or commodity_future_date_contract_data.variance120 is None \
                or commodity_future_date_contract_data.variance60 is None or commodity_future_date_contract_data.variance20 is None or commodity_future_date_contract_data.variance10 is None\
                or commodity_future_date_contract_data.variance5 is None:
            holding_position_date_number: int = BaseConfig.Fluctuation_Holding_Position_Date_Number
            up_down_percentage_backtrack_max_date: int = BaseConfig.Fluctuation_Up_Down_Percentage_Backtrack_Max_Date
            k_line_movement_pattern: int = KLineMovementPattern.Fluctuation
            Logger.warning("期货[%s]，日期[%s]在表c_f_date_contract_data中有数据，但是在表commodity_future_date_data中没有数据，因此只能这种取值，k线形态为[%s]，持仓时间为[%s]，最大回溯为[%s]",
                           commodity_future_date_contract_data.code, transaction_date, k_line_movement_pattern, holding_position_date_number, up_down_percentage_backtrack_max_date)
            if (len(quant2_account_log_list) + 1) % holding_position_date_number == 0:
                return k_line_movement_pattern, True
            else:
                return k_line_movement_pattern, False

        if (commodity_future_date_contract_data.variance250 is not None and commodity_future_date_contract_data.variance250 <= 40) or \
            (commodity_future_date_contract_data.variance120 is not None and commodity_future_date_contract_data.variance120 <= 30) or \
                (commodity_future_date_contract_data.variance60 is not None and commodity_future_date_contract_data.variance60 <= 20) or \
                (commodity_future_date_contract_data.variance20 is not None and commodity_future_date_contract_data.variance20 <= 10) or \
                (commodity_future_date_contract_data.variance10 is not None and commodity_future_date_contract_data.variance60 <= 5) or \
                (commodity_future_date_contract_data.variance5 is not None and commodity_future_date_contract_data.variance5 <= 2.5):
            # 震荡形态
            holding_position_date_number: int = BaseConfig.Fluctuation_Holding_Position_Date_Number
            up_down_percentage_backtrack_max_date: int = BaseConfig.Fluctuation_Up_Down_Percentage_Backtrack_Max_Date
            k_line_movement_pattern: int = KLineMovementPattern.Fluctuation
            Logger.info("期货[%s]，日期[%s]，k线形态为[%s]，250方差为[%s]，持仓时间为[%s]，最大回溯为[%s]", commodity_future_date_contract_data.code, transaction_date,
                        k_line_movement_pattern, commodity_future_date_contract_data.variance250, holding_position_date_number, up_down_percentage_backtrack_max_date)
        else:
            # 趋势形态
            holding_position_date_number: int = BaseConfig.Trend_Holding_Position_Date_Number
            up_down_percentage_backtrack_max_date: int = BaseConfig.Trend_Up_Down_Percentage_Backtrack_Max_Date
            k_line_movement_pattern: int = KLineMovementPattern.Trend
            Logger.info("期货[%s]，日期[%s]，k线形态为[%s]，250方差为[%s]，持仓时间为[%s]，最大回溯为[%s]", commodity_future_date_contract_data.code, transaction_date,
                        k_line_movement_pattern, commodity_future_date_contract_data.variance250, holding_position_date_number, up_down_percentage_backtrack_max_date)

        if (len(quant2_account_log_list) + 1) % holding_position_date_number == 0:
            return k_line_movement_pattern, True
        else:
            return k_line_movement_pattern, False

    def optimize2_k_line_movement_pattern_and_close_or_open_position_by_holding_position_time(self, transaction_date):
        """
        根据持仓时间，判断k线形态；判断当天是否应当平仓和开仓。True表示当天应当平仓和开仓，False表示不应当。查询optimize2
        """

        optimize2_account_list: list[Optimize2Account] = self.optimize2_account_dao.find_all()
        optimize2_account_log_list: list[Optimize2AccountLog] = self.optimize2_account_log_dao.find_by_account_name_order_by_date_desc(optimize2_account_list[0].account_name)

        if optimize2_account_log_list is None or len(optimize2_account_log_list) == 0:
            return KLineMovementPattern.Fluctuation, True

        # 查询当前的variance20
        unite_relative_price_index_date: UniteRelativePriceIndexDate = self.unite_relative_price_index_date_dao.find_by_transaction_date(transaction_date)

        # 由于数据缺失，因此只能按照震荡形态处理
        if unite_relative_price_index_date is None:
            holding_position_date_number: int = BaseConfig.Fluctuation_Holding_Position_Date_Number
            up_down_percentage_backtrack_max_date: int = BaseConfig.Fluctuation_Up_Down_Percentage_Backtrack_Max_Date
            k_line_movement_pattern: int = KLineMovementPattern.Fluctuation
            Logger.warning("日期[%s]在表c_f_date_contract_data中有数据，但是在表commodity_future_date_data中没有数据，因此只能这种取值，k线形态为[%s]，持仓时间为[%s]，最大回溯为[%s]",
                transaction_date, k_line_movement_pattern, holding_position_date_number, up_down_percentage_backtrack_max_date)
            if (len(optimize2_account_log_list) + 1) % holding_position_date_number == 0:
                return k_line_movement_pattern, True
            else:
                return k_line_movement_pattern, False

        if unite_relative_price_index_date.variance250 <= 40:
        # if 41 <= 40:
            # 震荡形态
            holding_position_date_number: int = BaseConfig.Fluctuation_Holding_Position_Date_Number
            up_down_percentage_backtrack_max_date: int = BaseConfig.Fluctuation_Up_Down_Percentage_Backtrack_Max_Date
            k_line_movement_pattern: int = KLineMovementPattern.Fluctuation
            Logger.info("k线形态为[%s]，250方差为[%s]，持仓时间为[%s]，最大回溯为[%s]", k_line_movement_pattern, unite_relative_price_index_date.variance250, holding_position_date_number,
                        up_down_percentage_backtrack_max_date)
        else:
            # 趋势形态
            holding_position_date_number: int = BaseConfig.Trend_Holding_Position_Date_Number
            up_down_percentage_backtrack_max_date: int = BaseConfig.Trend_Up_Down_Percentage_Backtrack_Max_Date
            k_line_movement_pattern: int = KLineMovementPattern.Trend
            Logger.info("k线形态为[%s]，250方差为[%s]，持仓时间为[%s]，最大回溯为[%s]", k_line_movement_pattern, unite_relative_price_index_date.variance250, holding_position_date_number,
                        up_down_percentage_backtrack_max_date)

        if (len(optimize2_account_log_list) + 1) % holding_position_date_number == 0:
            return k_line_movement_pattern, True
        else:
            return k_line_movement_pattern, False

    def close_or_open_position_by_up_down_percentage_with_n_date(self, date: str) -> bool:
        """
        根据最近n日涨跌百分比的变化决定是否平仓和开仓。如果上涨家数从大于50%变为小于50%（或者上涨家数从小于50%变为大于50%），则进行平仓和开仓。True表示当天应当平仓和开仓，False表示不应当
        """

        # 当前日期持有的多单和空单的数量
        holding_long_position_number, hold_short_position_number = self.quant2_commodity_future_transaction_record_dao.calculate_current_long_position_number_and_short_position_number()
        # 当前日期已经平仓的多单和已经平仓的空单的数量
        close_long_position_number: int = self.quant2_commodity_future_transaction_record_dao.calculate_close_long_position_number_by_date(date)
        close_short_position_number: int = self.quant2_commodity_future_transaction_record_dao.calculate_close_short_position_number_by_date(date)
        # 总持仓数
        hold_total_position_number: int = holding_long_position_number + hold_short_position_number + close_long_position_number + close_short_position_number

        # quant2_c_f_filter表中up_down_percentage_with_n_date字段大于等于0和小于0的数量
        filter_dict = {'up_down_percentage_with_n_date__gte': 0}
        gte_number: int = self.quant2_commodity_future_filter_dao.get_count(filter_dict, dict())
        filter_dict = {'up_down_percentage_with_n_date__lt': 0}
        lt_number: int = self.quant2_commodity_future_filter_dao.get_count(filter_dict, dict())
        # quant2_c_f_filter表的总记录数
        quant2_commodity_future_filter_number: int = gte_number + lt_number

        # 如果持仓总数为0，则开仓
        if hold_total_position_number == 0:
            return True

        # 如果昨天持有的多单大于等于50%，并且今天持有的空单大于等于50%；或者昨天持有的空单大于等于50%，并且今天持有的多单大于等于50%，则进行平仓和开仓
        if ((holding_long_position_number + close_long_position_number)/hold_total_position_number >= 0.6 and lt_number/quant2_commodity_future_filter_number >= 0.6) \
            or ((hold_short_position_number + close_short_position_number)/hold_total_position_number >= 0.6 and gte_number/quant2_commodity_future_filter_number >= 0.6):
            return True
        else:
            return False

    def calculate_long_position_and_short_position(self, quant2_commodity_future_filter_list: list[Quant2CommodityFutureFilter]):
        """
        计算多头仓位和空头仓位应该是多少
        """

        # 过滤后的期货品种数量
        quant2_commodity_future_filter_length: int = len(quant2_commodity_future_filter_list)
        # 涨跌百分比为正的数量
        positive_up_down_percentage_number: float = 0.0
        # 涨跌百分比为负的数量
        negative_up_down_percentage_number: float = 0.0

        # 计算涨跌百分比为正的数量和为负的数量
        for quant2_commodity_future_filter in quant2_commodity_future_filter_list:
            if quant2_commodity_future_filter.up_down_percentage_with_n_date >= 0:
                positive_up_down_percentage_number = positive_up_down_percentage_number + 1
            else:
                negative_up_down_percentage_number = negative_up_down_percentage_number + 1

        # 计算多头仓位和空头仓位
        should_long_position_number: int = round(positive_up_down_percentage_number / quant2_commodity_future_filter_length * MultiFactorConfig.Max_Hold_Commodity_Future_Number)
        should_short_position_number: int = round(negative_up_down_percentage_number / quant2_commodity_future_filter_length * MultiFactorConfig.Max_Hold_Commodity_Future_Number)

        if should_short_position_number == 0:
            return should_long_position_number - 1, 1

        if should_long_position_number == 0:
            return 1, should_short_position_number - 1

        if should_long_position_number + should_short_position_number > MultiFactorConfig.Max_Hold_Commodity_Future_Number:
            if should_long_position_number > should_short_position_number:
                should_long_position_number = should_long_position_number -1
            elif should_long_position_number < should_short_position_number:
                should_short_position_number = should_short_position_number -1
            else:
                should_short_position_number = should_short_position_number - 1

        return should_long_position_number, should_short_position_number

    def calculate_up_down_percentage_backtrack_date(self, date: str):
        """
        计算涨跌百分比的回溯时间
        """

        # 计算n天之前的日期
        # one_year_date: str = DatetimeUtil.datetime_to_str(DatetimeUtil.backwardNDate(date, MultiFactorConfig.Variance20_Backward_N_Date), DatetimeFormat.Date_Format)
        # 查询最近n天内variance20的平均值
        # average_variance20: float = self.unite_relative_price_index_date_dao.find_average_variance20_between_transaction_date(one_year_date, date)

        # 查询当前的variance20
        unite_relative_price_index_date: UniteRelativePriceIndexDate = self.unite_relative_price_index_date_dao.find_by_transaction_date(date)
        # current_variance: float = (unite_relative_price_index_date.variance20 + unite_relative_price_index_date.variance60 + unite_relative_price_index_date.variance120)/3

        # 计算回溯时间
        # if current_variance >= average_variance20 / 2:
        #     MultiFactorConfig.Holding_Position_Date_Number = 2
        #     return MultiFactorConfig.Up_Down_Percentage_Backtrack_Max_Date
        # else:
        #     MultiFactorConfig.Holding_Position_Date_Number = 5
        #     return MultiFactorConfig.Up_Down_Percentage_Backtrack_Max_Date / 10

        # MultiFactorConfig.Holding_Position_Date_Number = 5
        # return 2

        # 由于数据缺失，因此只能按照震荡形态处理
        if unite_relative_price_index_date is None:
            holding_position_date_number: int = BaseConfig.Fluctuation_Holding_Position_Date_Number
            up_down_percentage_backtrack_max_date: int = BaseConfig.Fluctuation_Up_Down_Percentage_Backtrack_Max_Date
            k_line_movement_pattern: int = KLineMovementPattern.Fluctuation
            Logger.warning("日期[%s]在表c_f_date_contract_data中有数据，但是在表commodity_future_date_data中没有数据，因此只能这种取值，k线形态为[%s]，持仓时间为[%s]，最大回溯为[%s]",
                date, k_line_movement_pattern, holding_position_date_number, up_down_percentage_backtrack_max_date)
            return up_down_percentage_backtrack_max_date

        if unite_relative_price_index_date.variance250 <= 40:
        # if 41 <= 40:
            # 震荡形态
            holding_position_date_number: int = BaseConfig.Fluctuation_Holding_Position_Date_Number
            up_down_percentage_backtrack_max_date: int = BaseConfig.Fluctuation_Up_Down_Percentage_Backtrack_Max_Date
            k_line_movement_pattern: int = KLineMovementPattern.Fluctuation
            Logger.info("k线形态为[%s]，250方差为[%s]，持仓时间为[%s]，最大回溯为[%s]", k_line_movement_pattern, unite_relative_price_index_date.variance250,
                        holding_position_date_number, up_down_percentage_backtrack_max_date)
            return up_down_percentage_backtrack_max_date
        else:
            # 趋势形态
            holding_position_date_number: int = BaseConfig.Trend_Holding_Position_Date_Number
            up_down_percentage_backtrack_max_date: int = BaseConfig.Trend_Up_Down_Percentage_Backtrack_Max_Date
            k_line_movement_pattern: int = KLineMovementPattern.Trend
            Logger.info("k线形态为[%s]，250方差为[%s]，持仓时间为[%s]，最大回溯为[%s]", k_line_movement_pattern, unite_relative_price_index_date.variance250,
                        holding_position_date_number, up_down_percentage_backtrack_max_date)
            return up_down_percentage_backtrack_max_date

    def find_should_hold_long_and_short_commodity_future_filter_list(self, quant2_account_index: int, should_long_position_number: int, should_short_position_number: int) -> list[Quant2CommodityFutureFilter]:
        """
        根据账号排序，查询应该持有的多头期货和空头期货列表
        """

        should_long_commodity_future_filter_list: list[Quant2CommodityFutureFilter] = self.quant2_commodity_future_filter_dao.page_with_order(
            False, quant2_account_index + 1, should_long_position_number)
        should_short_commodity_future_filter_list: list[Quant2CommodityFutureFilter] = self.quant2_commodity_future_filter_dao.page_with_order(
            True, quant2_account_index + 1, should_short_position_number)

        # 注意，此处如果不删除删除已经持仓的期货，就会出现多个账号同时持有一个品种的情况
        not_close_quant2_commodity_future_transaction_record_list: list[Quant2CommodityFutureTransactionRecord] = self.quant2_commodity_future_transaction_record_dao.find_not_close_position()
        if not_close_quant2_commodity_future_transaction_record_list is not None and len(not_close_quant2_commodity_future_transaction_record_list) > 0:
            _should_long_commodity_future_filter_list: list[Quant2CommodityFutureFilter] = list()
            _should_short_commodity_future_filter_list: list[Quant2CommodityFutureFilter] = list()

            for should_long_commodity_future_filter in should_long_commodity_future_filter_list:
                if should_long_commodity_future_filter not in list(map(lambda x: x.code, not_close_quant2_commodity_future_transaction_record_list)):
                    _should_long_commodity_future_filter_list.append(should_long_commodity_future_filter)
            for should_short_commodity_future_filter in _should_short_commodity_future_filter_list:
                if should_short_commodity_future_filter not in list(map(lambda x: x.code, not_close_quant2_commodity_future_transaction_record_list)):
                    _should_short_commodity_future_filter_list.append(should_short_commodity_future_filter)

            return _should_long_commodity_future_filter_list, _should_short_commodity_future_filter_list
        else:
            return should_long_commodity_future_filter_list, should_short_commodity_future_filter_list

    def find_quant2_actual_long_position_number(self, account_name: str, direction: int) -> int:
        """
        查询实际持仓期货中多头数量
        """

        filter_dict = {'account_name': account_name, 'direction': direction, 'buy_date__isnull': False, 'sell_date__isnull': True}
        actual_long_quant2_commodity_future_transaction_record_list: list[Quant2CommodityFutureTransactionRecord] = self.quant2_commodity_future_transaction_record_dao.find_list(filter_dict, dict(), dict())
        actual_long_position_number: int = len(actual_long_quant2_commodity_future_transaction_record_list)
        return actual_long_position_number

    def find_quant2_actual_short_position_number(self, account_name: str, direction: int) -> int:
        """
        查询实际持仓期货中空头数量
        """

        filter_dict = {'account_name': account_name, 'direction': direction, 'buy_date__isnull': True, 'sell_date__isnull': False}
        actual_short_quant2_commodity_future_transaction_record_list: list[Quant2CommodityFutureTransactionRecord] = self.quant2_commodity_future_transaction_record_dao.find_list(filter_dict, dict(), dict())
        actual_short_position_number: int = len(actual_short_quant2_commodity_future_transaction_record_list)
        return actual_short_position_number

    def find_optimize2_actual_long_position_number(self, account_name: str, direction: int) -> int:
        """
        查询实际持仓期货中多头数量
        """

        filter_dict = {'account_name': account_name, 'direction': direction, 'buy_date__isnull': False, 'sell_date__isnull': True}
        actual_long_optimize2_commodity_future_transaction_record_list: list[Optimize2CommodityFutureTransactionRecord] = self.optimize2_commodity_future_transaction_record_dao.find_list(filter_dict, dict(), dict())
        actual_long_position_number: int = len(actual_long_optimize2_commodity_future_transaction_record_list)
        return actual_long_position_number

    def find_optimize2_actual_short_position_number(self, account_name: str, direction: int) -> int:
        """
        查询实际持仓期货中空头数量
        """

        filter_dict = {'account_name': account_name, 'direction': direction, 'buy_date__isnull': True, 'sell_date__isnull': False}
        actual_short_optimize2_commodity_future_transaction_record_list: list[Optimize2CommodityFutureTransactionRecord] = self.optimize2_commodity_future_transaction_record_dao.find_list(filter_dict, dict(), dict())
        actual_short_position_number: int = len(actual_short_optimize2_commodity_future_transaction_record_list)
        return actual_short_position_number